package com.yami.shop.mystery.common.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.model.Product;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.mystery.common.dao.ActivityRuleMapper;
import com.yami.shop.mystery.common.dto.ActivityPresellDto;
import com.yami.shop.mystery.common.dto.ActivityRuleOptions;
import com.yami.shop.mystery.common.enums.ActivityRuleConditionEnum;
import com.yami.shop.mystery.common.enums.ActivityRuleEnum;
import com.yami.shop.mystery.common.model.ActivityRule;
import com.yami.shop.mystery.common.service.ActivityRuleService;
import com.yami.shop.mystery.common.vo.ActivityRulePageVo;
import com.yami.shop.security.common.util.AuthUserContext;
import groovy.lang.Tuple;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wxf
 * @date 2023/4/17 9:46
 */
@Service
@AllArgsConstructor
public class ActivityRuleServiceImpl extends ServiceImpl<ActivityRuleMapper, ActivityRule> implements ActivityRuleService {

    private final ActivityRuleMapper ruleMapper;

    private final ProductMapper productMapper;

    @Override
    public IPage<ActivityRule> pageList(PageParam<ActivityRule> page, ActivityRulePageVo dto) {

        IPage<ActivityRule> pageRule = ruleMapper.pageList(page, dto);
        for (ActivityRule rule : pageRule.getRecords()) {
            if (!Objects.isNull(rule.getRuleType())) {
                rule.setRuleTypeName(ActivityRuleEnum.instance(rule.getRuleType()).getLabel());
            }
            if (!Objects.isNull(rule.getConditionType())) {
                rule.setConditionTypeName(ActivityRuleConditionEnum.instance(rule.getConditionType()).getLabel());
            }
            if (!Objects.isNull(rule.getProdId())) {
                Product product = productMapper.selectById(rule.getProdId());
                rule.setProdName(product == null ? "" : product.getProdName());
            }
        }
        return pageRule;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(ActivityRule bean) {

        boolean saveOrUpdate = null != bean.getRuleId() && bean.getRuleId() != 0 ? true : false;

        Long shopId = AuthUserContext.get().getShopId();
        List<ActivityRule> list = ruleMapper.selectList(Wrappers.lambdaQuery(ActivityRule.class).eq(ActivityRule::getShopId, shopId)
                .eq(ActivityRule::getRuleName, bean.getRuleName()).eq(ActivityRule::getDelFlag, 0)
                .notIn(saveOrUpdate,ActivityRule::getRuleId,bean.getRuleId()));
        if (list.size() > 0) {
            throw new YamiShopBindException("活动规则名称不能重复");
        }
        bean.setShopId(shopId);
        if (saveOrUpdate) {
            bean.setUpdateTime(new Date());
            bean.setUpdateBy(AuthUserContext.get().getUserId());
        } else {
            bean.setCreateTime(new Date());
            bean.setCreateBy(AuthUserContext.get().getUserId());
        }
        return super.saveOrUpdate(bean);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeIds(List<Long> ids) {
        List<ActivityRule> data = ids.stream().map(id -> new ActivityRule(id, 1)).collect(Collectors.toList());
        this.updateBatchById(data);
    }

    @Override
    public ActivityRule detail(Long ruleId) {

        ActivityRule detail = super.getById(ruleId);
        if (detail.getProdId() != null) {
            Product product = productMapper.selectById(detail.getProdId());
            detail.setProdName(product.getProdName());
            detail.setProduct(product);
        }
        return detail;
    }

    @Override
    public Boolean updateStatus(String id, String status) {
        return ruleMapper.updateStatus(id, status) > 0 ? true : false;
    }

    @Override
    public List<ActivityRuleOptions> getRuleTypeOptions() {
        List<ActivityRuleOptions> list = new ArrayList<>();
        ActivityRuleEnum[] enums = ActivityRuleEnum.values();
        for (ActivityRuleEnum statusEnum : enums) {
            ActivityRuleOptions options = new ActivityRuleOptions();
            options.setLabel(statusEnum.getLabel());
            options.setValue(statusEnum.getValue());
            list.add(options);
        }
        return list;
    }

    @Override
    public List<ActivityRuleOptions> getConditionTypeOptions() {
        List<ActivityRuleOptions> list = new ArrayList<>();
        ActivityRuleConditionEnum[] enums = ActivityRuleConditionEnum.values();
        for (ActivityRuleConditionEnum statusEnum : enums) {
            ActivityRuleOptions options = new ActivityRuleOptions();
            options.setLabel(statusEnum.getLabel());
            options.setValue(statusEnum.getValue());
            list.add(options);
        }
        return list;
    }

    /**
     *  通过规则ids 查询规则对象列表
     *
     * @param activityRuleIds
     * @return
     */
    @Override
    public List<ActivityRule> selectByRuleId(String activityRuleIds) {

        if (StringUtils.isBlank(activityRuleIds)) {
            return new ArrayList<>();
        }

        List<String> ruleIdStr = Arrays.asList(activityRuleIds.split(","));
        List<Long> ruleIds = new ArrayList<>();
        CollectionUtils.collect(ruleIdStr , input -> Long.valueOf(input.toString()), ruleIds);

        // 查询所有规则
        List<ActivityRule> ruleList = ruleMapper.selectList(Wrappers.lambdaQuery(ActivityRule.class)
                .in(ActivityRule::getRuleId,ruleIds).eq(ActivityRule::getDelFlag, 0).eq(ActivityRule::getStatus,0));

        return ruleList;
    }

    /**
     *  规则校验
     *
     * @param presell
     * @return 第一位：是否可售卖 第二位：规则类型 第三位：限购数 第四位：满足条件对应的规则对象
     */
    @Override
    public Tuple checkActivityRule(ActivityPresellDto presell, String userId) {

        if (ObjectUtil.isNull(presell) || StringUtils.isBlank(presell.getActivityRule())) {
            return Tuple.tuple(false, null, null, null);
        }
        List<String> ruleIdStr = Arrays.asList(presell.getActivityRule().split(","));
        List<Long> ruleIds = new ArrayList<>();
        CollectionUtils.collect(ruleIdStr , input -> Long.valueOf(input.toString()), ruleIds);

        // 查询所有规则
        List<ActivityRule> ruleList = this.selectByRuleId(presell.getActivityRule());

        // 按规则类型转分组
        Map<String, List<ActivityRule>> map = ruleList.stream().collect(Collectors.groupingBy(ActivityRule::getRuleType));

        //首先校验优惠、其次优先,后面规则无先后顺序
        Tuple tupleDis = ruleCheck(map.get(ActivityRuleEnum.DISCOUNTS.getValue()), ActivityRuleEnum.DISCOUNTS.getValue());
        if ((boolean)tupleDis.get(0)) {

            return tupleDis;
        }

        Tuple tuplePreemp = ruleCheck(map.get(ActivityRuleEnum.PREEMPTION.getValue()),ActivityRuleEnum.PREEMPTION.getValue());
        if ((boolean)tuplePreemp.get(0)) {

            return tuplePreemp;
        }

        return Tuple.tuple(false, null, null, null);
    }

    /**
     *  同一类型规则校验
     *
     * @param list
     * @param ruleType
     * @return
     */
    @Override
    public Tuple ruleCheck(List<ActivityRule> list, String ruleType) {

        if (CollectionUtils.isEmpty(list)) {
            return Tuple.tuple(false, ruleType, null, null);
        }
        boolean flag = false;
        long num = 0L;
        ActivityRule numRule = null;
        for (ActivityRule rule : list) {
            if (singleRuleCheck(rule)) {
                flag = true;
                if(ObjectUtil.isEmpty(numRule)){
                    numRule = rule;
                }
                if (rule.getConditionNum() > num) {
                    num = rule.getConditionNum();
                    numRule = rule;
                }
            }
        }
        return Tuple.tuple(flag, ruleType, num, numRule);
    }

    @Override
    public List<ActivityRule> getList(ActivityRulePageVo vo) {
        QueryWrapper<ActivityRule> activityRuleQueryWrapper = new QueryWrapper<>();
        activityRuleQueryWrapper.like(ObjectUtil.isNotEmpty(vo.getRuleName()),"rule_name",vo.getRuleName());
        activityRuleQueryWrapper.eq(ObjectUtil.isNotEmpty(vo.getRuleType()),"rule_type",vo.getRuleType());
        activityRuleQueryWrapper.eq("shop_id",vo.getShopId());
        activityRuleQueryWrapper.orderByDesc("create_time");
        activityRuleQueryWrapper.eq("status",0);
        return ruleMapper.selectList(activityRuleQueryWrapper);
    }


    /**
     *  校验单个活动规则
     *
     * @param rule
     * @return
     */
    private boolean singleRuleCheck(ActivityRule rule) {
        ActivityRuleEnum ruleEnum = ActivityRuleEnum.instance(rule.getRuleType());
        Date now = new Date();
        boolean flag = false;
        switch (ruleEnum) {
            case PREEMPTION: //优先购
            case DISCOUNTS : //优惠购
            case APPLY : //报名
                if ((rule.getStartTime().getTime() <= now.getTime() && now.getTime() <= rule.getEndTime().getTime())
                        || rule.getStartTime().getTime() > now.getTime()) {
                    flag = true;
                }
                break;
            case INVITENUM : //邀请人数

                break;
            case PAYMENTAMOUNT : //支付金额

                break;
            case PAYMENTTIME : // 最近支付时间

                break;
            case REGISTERTIME : // 注册时间

                break;
            case PAYMENTNUM : //支付次数

                break;
            case HOLDPRODUCT : //持有艺术品

                break;
            case AUTOREPLENISH : //自动补货

                break;
            default:

        }

        return flag;
    }

}
